#! /usr/bin/env python
#coding=utf-8

import os
import sys
sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), "../"))
sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), "../../"))

import loader
from utils import ResterHelper
from utils import ResterStringBuilder

class ElfSymbolRest(loader.SymbolBase, ResterStringBuilder):
	def getStr(self, xargs=None, keys=None):
		if xargs and "format" in xargs and xargs["format"] == "xml":
			sorted_keys = ("caller", "library", "name", "bits", "section") # "demangle",
		else:
			sorted_keys = ("caller", "library", "name", "bits", "section")
		return ResterStringBuilder.getStr(self, xargs, sorted_keys)

class ElfDupSymbolResults(ResterStringBuilder):
	DUP_SYMBOL_INFO_KEYS = ("name", "count", "calls", "demangle")
	def __init__(self, keys, row):
		for idx, key in enumerate(keys):
			self[key] = row[idx]

	def getStr(self, xargs=None, keys=None):
		ordered_keys = ElfDupSymbolResults.DUP_SYMBOL_INFO_KEYS
		return ResterStringBuilder.getStr(self, xargs, ordered_keys)

class CallsCntResults(ResterStringBuilder):
	CALLS_CNT_INFO_KEYS = ("id", "parent_id", "name", "demangle", "library", "count")
	def __init__(self, keys, row):
		for idx, key in enumerate(keys):
			if not row[idx]:
				self[key] = 0
			else:
				self[key] = row[idx]

	def getStr(self, xargs=None, keys=None):
		ordered_keys = CallsCntResults.CALLS_CNT_INFO_KEYS
		return ResterStringBuilder.getStr(self, xargs, ordered_keys)

class CallsDetailResults(ResterStringBuilder):
	CALLS_DETAIL_KEYS = ("symbol_id", "callee_id", "caller_id", "name", "demangle", "library", "caller")
	def __init__(self, keys, row):
		for idx, key in enumerate(keys):
			if not row[idx]:
				self[key] = 0
			else:
				self[key] = row[idx]

	def getStr(self, xargs=None, keys=None):
		ordered_keys = CallsDetailResults.CALLS_DETAIL_KEYS
		return ResterStringBuilder.getStr(self, xargs, ordered_keys)

class SymbolsRestMgr(object):
	def __init__(self, product):
		self._product  = product

	def get_all(self, xargs):
		keys = ElfDupSymbolResults.DUP_SYMBOL_INFO_KEYS
		sqlcmd = "select %s from symbol_names where count > 1" % ", ".join(keys)
		cursor = self._product.getCursor()
		cursor.execute(sqlcmd)

		symbols = []
		for row in cursor:
			symbols.append(ElfDupSymbolResults(keys, row))
		return symbols

	def doRestRequest(self, id, mod, args):
		mCmdMap = {
			'modules':self._dbGetModulesByName,
			'calls':self._dbGetCallsInfoBySymbolName,
			'details':self._dbGetCallsDetailsBySymbolId,
			'search':self._dbSearchSymbolsByName
		}
		vals = mCmdMap[mod](id, args)
		return ResterHelper.build_array_content(vals, args)

	def _dbGetModulesByName(self, id, args):
		keys = CallsCntResults.CALLS_CNT_INFO_KEYS
		sqlcmd = 'select %s from symbols_count where name="%s"' % (", ".join(keys), id)
		cursor = self._product.getCursor()
		cursor.execute(sqlcmd)

		objects = []
		for row in cursor:
			objects.append(CallsCntResults(keys, row))
		return objects

	def _dbGetCallsInfoBySymbolName(self, id, args):
		keys = CallsCntResults.CALLS_CNT_INFO_KEYS
		sqlcmd = 'select %s from calls_count_details where name="%s"' % (", ".join(keys), id)
		cursor = self._product.getCursor()
		cursor.execute(sqlcmd)

		objects = []
		for row in cursor:
			objects.append(CallsCntResults(keys, row))
		return objects

	def _dbGetCallsDetailsBySymbolId(self, id, args):
		keys = CallsDetailResults.CALLS_DETAIL_KEYS
		sqlcmd = 'select %s from call_details where symbol_id=%d' % (", ".join(keys), int(id))
		cursor = self._product.getCursor()
		cursor.execute(sqlcmd)

		objects = []
		for row in cursor:
			objects.append(CallsDetailResults(keys, row))
		return objects

	def _dbSearchSymbolsByName(self, id, args):
		keys = ElfDupSymbolResults.DUP_SYMBOL_INFO_KEYS
		sqlcmd = 'select %s from symbol_names where demangle like "%%%s%%" limit 5000' % (", ".join(keys), id)
		cursor = self._product.getCursor()
		cursor.execute(sqlcmd)

		symbols = []
		for row in cursor:
			symbols.append(ElfDupSymbolResults(keys, row))
		return symbols
